package com.hospital.schedule.module.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hospital.common.dto.schedule.module.*;
import com.hospital.common.enums.schedule.module.HourSlotType;
import com.hospital.common.pojo.TDoctorInfo;
import com.hospital.common.pojo.TDoctorLeaveRecord;
import com.hospital.common.pojo.TDoctorSchedule;
import com.hospital.common.pojo.TUser;
import com.hospital.common.utils.TimeUtils;
import com.hospital.common.vo.schedule.module.FindDoctorScheduleByAdminVo;
import com.hospital.common.vo.schedule.module.FindDoctorScheduleByAdminVoDoctorInfo;
import com.hospital.common.vo.schedule.module.FindDoctorScheduleByDoctorVo;
import com.hospital.common.vo.schedule.module.FindDoctorScheduleByTimeVo;
import com.hospital.schedule.module.mapper.TDoctorScheduleMapper;
import com.hospital.schedule.module.service.ITDepartmentService;
import com.hospital.schedule.module.service.ITDoctorInfoService;
import com.hospital.schedule.module.service.ITDoctorScheduleService;
import com.hospital.schedule.module.service.ITUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 排班表 服务实现类
 * </p>
 *
 * @author author
 * @since 2025-09-11
 */
@Service
public class TDoctorScheduleServiceImpl extends ServiceImpl<TDoctorScheduleMapper, TDoctorSchedule> implements ITDoctorScheduleService {

    @Autowired
    private TDoctorScheduleMapper tDoctorScheduleMapper;
    @Autowired
    private ITDoctorInfoService tDoctorInfoService;
    @Autowired
    private ITDepartmentService tDepartmentService;
    @Autowired
    private ITUserService userService;
    /**
     * 添加排班信息
      * @param addDoctorScheduleDtoList
      * @return
      */
    @Override
    @Transactional
    public boolean addDoctorSchedule(List<AddDoctorScheduleDto> addDoctorScheduleDtoList) {
        for (AddDoctorScheduleDto addDoctorScheduleDto : addDoctorScheduleDtoList) {
            addDoctorScheduleDto.setScheduledDate(TimeUtils.formatToStartOfDay(addDoctorScheduleDto.getScheduledDate()));
        }
        List<TDoctorSchedule> tDoctorScheduleList = new ArrayList<>();
        if(addDoctorScheduleDtoList.get(0).getScheduleType()==0) {
            for (AddDoctorScheduleDto addDoctorScheduleDto : addDoctorScheduleDtoList) {
                List<TDoctorSchedule> tDoctorSchedules = new ArrayList<>();
                if (addDoctorScheduleDto.getSession() == 0) {
                    for (int i = 0; i < 3; i++) {
                        TDoctorSchedule tDoctorSchedule = BeanUtil.copyProperties
                                (addDoctorScheduleDto, TDoctorSchedule.class);
                        tDoctorSchedule.setHourSlot(i);
                        tDoctorSchedules.add(tDoctorSchedule);
                    }
                } else {
                    for (int i = 0; i < 3; i++) {
                        TDoctorSchedule tDoctorSchedule = BeanUtil.copyProperties
                                (addDoctorScheduleDto, TDoctorSchedule.class);
                        tDoctorSchedule.setHourSlot(i + 3);
                        tDoctorSchedules.add(tDoctorSchedule);
                    }
                }
                tDoctorScheduleList.addAll(tDoctorSchedules);
            }
        }else{
            tDoctorScheduleList = addDoctorScheduleDtoList.stream()
                    .map(addDoctorScheduleDto ->
                            BeanUtil.copyProperties(addDoctorScheduleDto, TDoctorSchedule.class)).toList();
        }
        System.out.println("tDoctorScheduleList.get(0).getScheduledDate() = " + tDoctorScheduleList.get(0).getScheduledDate());
        return this.saveBatch(tDoctorScheduleList);
    }

    @Override
    public List<FindDoctorScheduleByDoctorVo> findDoctorScheduleByDoctor
            (FindDoctorScheduleByDoctorDto findDoctorScheduleByDoctorDto) {
        findDoctorScheduleByDoctorDto.setScheduledDate(TimeUtils
                .formatToStartOfDay(findDoctorScheduleByDoctorDto.getScheduledDate()));
        List<TDoctorSchedule> tDoctorScheduleList = tDoctorScheduleMapper
                .findDoctorScheduleByDoctor(findDoctorScheduleByDoctorDto);
        List<FindDoctorScheduleByDoctorVo> findDoctorScheduleByDoctorVoList =
                tDoctorScheduleList.stream().map(tDoctorSchedule ->
                        BeanUtil.copyProperties(tDoctorSchedule,
                                FindDoctorScheduleByDoctorVo.class)).toList();
        if(findDoctorScheduleByDoctorDto.getScheduleType()==0){
            for (FindDoctorScheduleByDoctorVo findDoctorScheduleByDoctorVo
                    : findDoctorScheduleByDoctorVoList) {
                findDoctorScheduleByDoctorVo.setTimeSlot(
                        HourSlotType.fromCode(findDoctorScheduleByDoctorVo.getHourSlot())
                );

            }
        }
        for (FindDoctorScheduleByDoctorVo findDoctorScheduleByDoctorVo
                : findDoctorScheduleByDoctorVoList) {
            findDoctorScheduleByDoctorVo.setTDoctor(
                    userService.getById(findDoctorScheduleByDoctorDto.getDoctorId())
            );
            findDoctorScheduleByDoctorVo.setTDoctorInfo
                    (tDoctorInfoService.findDoctorByUserId(findDoctorScheduleByDoctorDto.getDoctorId()));
        }
        return findDoctorScheduleByDoctorVoList;
    }

    @Override
    public List<FindDoctorScheduleByAdminVo> findDoctorScheduleByAdmin
            (FindDoctorScheduleByAdminDto findDoctorScheduleByAdminDto) {
        findDoctorScheduleByAdminDto.setStartTime(TimeUtils.formatToStartOfDay
                (findDoctorScheduleByAdminDto.getStartTime()));
        findDoctorScheduleByAdminDto.setEndTime(TimeUtils.formatToEndOfDay(
                (findDoctorScheduleByAdminDto.getEndTime())));
        List<TDoctorSchedule> tDoctorScheduleList = tDoctorScheduleMapper
                .findDoctorScheduleByAdmin(findDoctorScheduleByAdminDto);
        List<FindDoctorScheduleByAdminVo> findDoctorScheduleByAdminVoList =
                tDoctorScheduleList.stream()
                        .map(tDoctorSchedule ->
                                BeanUtil.copyProperties(tDoctorSchedule,
                                        FindDoctorScheduleByAdminVo.class)).toList();
        for (FindDoctorScheduleByAdminVo findDoctorScheduleByAdminVo :
                findDoctorScheduleByAdminVoList) {
            if(findDoctorScheduleByAdminVo.getScheduleType()==0){
                System.out.println("findDoctorScheduleByAdminVo.getScheduleType() = " + findDoctorScheduleByAdminVo.getScheduleType());
                findDoctorScheduleByAdminVo.setTimeSlot(
                        HourSlotType.fromCode(findDoctorScheduleByAdminVo.getHourSlot())
                );
            }

            TDoctorInfo doctorByUserId = tDoctorInfoService.findDoctorByUserId(findDoctorScheduleByAdminVo.getDoctorId());
            FindDoctorScheduleByAdminVoDoctorInfo doctorInfo =
                    new FindDoctorScheduleByAdminVoDoctorInfo();
            doctorInfo.setId(findDoctorScheduleByAdminVo.getDoctorId());
            doctorInfo.setEducationLevel(doctorByUserId.getEducationLevel());
            doctorInfo.setTitle(doctorByUserId.getTitle());
            doctorInfo.setYearsOfExperience(doctorByUserId.getYearsOfExperience());
            TUser user = userService.getById(findDoctorScheduleByAdminVo.getDoctorId());
            doctorInfo.setDoctorName(user.getName());
            findDoctorScheduleByAdminVo.setFindDoctorScheduleByAdminVoDoctorInfo(doctorInfo);
        }
        return findDoctorScheduleByAdminVoList;
    }

    @Override
    public Integer updateScheduleByLeaveRecord(TDoctorLeaveRecord tDoctorLeaveRecord) {
        return tDoctorScheduleMapper.updateScheduleByLeaveRecord(tDoctorLeaveRecord);
    }

    /**
     * 批量更新排班信息，同意请假
     * @param doctorLeaveRecord
     * @return
     */
    @Override
    public Integer updateScheduleByAgreeLeaveRecord(TDoctorLeaveRecord doctorLeaveRecord) {
        return tDoctorScheduleMapper.updateScheduleByAgreeLeaveRecord(doctorLeaveRecord);
    }

    @Override
    public Integer updateScheduleByRefuseLeaveRecord(TDoctorLeaveRecord tDoctorLeaveRecord) {
        return tDoctorScheduleMapper.updateScheduleByRefuseLeaveRecord(tDoctorLeaveRecord);
    }

    @Override
    public Integer disagreeLeaveRecordByAdmin(TDoctorLeaveRecord tDoctorLeaveRecord) {
        return tDoctorScheduleMapper.disagreeLeaveRecordByAdmin(tDoctorLeaveRecord);
    }

    @Override
    public List<TDoctorSchedule> findDoctorScheduleByAttend(AddDoctorAttendanceDto addDoctorAttendanceDto) {
        return tDoctorScheduleMapper.findDoctorScheduleByAttend(addDoctorAttendanceDto);
    }

    @Override
    public List<Long> findDoctorId(String formatToEndOfDay, String formatToStartOfDay) {
        return tDoctorScheduleMapper.findDoctorId( formatToEndOfDay,  formatToStartOfDay);
    }

    @Override
    public List<Long> fineDoctorByDoctorSchedule(Long departmentId ,String startTime, String endTime) {
        return tDoctorScheduleMapper.fineDoctorByDoctorSchedule(departmentId,startTime,endTime);
    }

    @Override
    public FindDoctorScheduleByTimeVo findDoctorScheduleByTime(FindDoctorScheduleByTimeDto findDoctorScheduleByTimeDto) {
        String today = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        findDoctorScheduleByTimeDto.setStartTime(TimeUtils.formatToStartOfDay(today));
        findDoctorScheduleByTimeDto.setEndTime(TimeUtils.formatToEndOfDay(today));
        List<TDoctorSchedule> count = tDoctorScheduleMapper.findDoctorScheduleByTime(findDoctorScheduleByTimeDto);
        List<FindDoctorScheduleByTimeVo> findDoctorScheduleByTimeVoList = new ArrayList<>();
        FindDoctorScheduleByTimeVo findDoctorScheduleByTimeVo = new FindDoctorScheduleByTimeVo();
        List<TDoctorSchedule> tDoctorSchedules = new ArrayList<>();
        for (TDoctorSchedule tDoctorSchedule : count) {

            if(tDoctorSchedule.getScheduleType()==0){
                tDoctorSchedules.add(tDoctorSchedule);
                findDoctorScheduleByTimeVo.setScheduleType(0);
                findDoctorScheduleByTimeVo.setState(1);
                if(findDoctorScheduleByTimeVoList.size()>1){
                    if(findDoctorScheduleByTimeVoList.get(0).getScheduleType()==0){
                        continue;
                    }
                }
                findDoctorScheduleByTimeVoList.add(findDoctorScheduleByTimeVo);
            }else if(tDoctorSchedule.getScheduleType()==1){
                findDoctorScheduleByTimeVo.setScheduleType(1);
                findDoctorScheduleByTimeVo.setState(1);
                if(findDoctorScheduleByTimeVoList.size()>1){
                    if(findDoctorScheduleByTimeVoList.get(0).getScheduleType()==1){
                        continue;
                    }
                }
                findDoctorScheduleByTimeVoList.add(findDoctorScheduleByTimeVo);
            }

        }
        if (findDoctorScheduleByTimeVoList.size()>0){
            for (FindDoctorScheduleByTimeVo doctorScheduleByTimeVo : findDoctorScheduleByTimeVoList) {
                if(doctorScheduleByTimeVo.getScheduleType()==0){
                    doctorScheduleByTimeVo.setTDoctorScheduleList(tDoctorSchedules);
                }
            }
        }

        if(findDoctorScheduleByTimeVoList.size()<2){
            if(findDoctorScheduleByTimeVoList.size()==1){
                if(findDoctorScheduleByTimeVoList.get(0).getScheduleType()==0){
                    findDoctorScheduleByTimeVoList.add(new FindDoctorScheduleByTimeVo(1,0));
                }
            }
            if(findDoctorScheduleByTimeVoList.size()==1){
                if(findDoctorScheduleByTimeVoList.get(0).getScheduleType()==1){
                    findDoctorScheduleByTimeVoList.add(new FindDoctorScheduleByTimeVo(0,0));
                }
            }
            if(findDoctorScheduleByTimeVoList.size()==0){
                findDoctorScheduleByTimeVoList.add(new FindDoctorScheduleByTimeVo(0,0));
                findDoctorScheduleByTimeVoList.add(new FindDoctorScheduleByTimeVo(1,0));
            }
        }
        return findDoctorScheduleByTimeVoList.get(0);
    }

    @Override
    public Integer fineDoctorBySchedule(FindDoctorScheduleOfScheduleDto findDoctorScheduleOfScheduleDto) {
        String today = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        findDoctorScheduleOfScheduleDto.setStartTime(TimeUtils.formatToStartOfDay
                (today));
        findDoctorScheduleOfScheduleDto.setEndTime(TimeUtils.formatToEndOfDay
                (today));
        return tDoctorScheduleMapper.fineDoctorBySchedule(findDoctorScheduleOfScheduleDto)>0?1:0;
    }
}
